package com.heima.service.impl;

import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.IdUtil;
import cn.hutool.jwt.JWTUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.heima.mapper.UserMapper;
import com.heima.model.dtos.LoginAuthDto;
import com.heima.model.pojos.User;
import com.heima.model.user.dtos.FollowDto;
import com.heima.model.vos.LoginAuthVo;
import com.heima.model.vos.UserBaseVo;
import com.heima.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author itheima
 * @since 2022-12-28
 */
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public LoginAuthVo login(LoginAuthDto dto) {

        // 1. 入参判断
        // 1.1 判断dto是否为空
        if (dto == null) {
            throw new RuntimeException("入参不能为空");
        }
        // 1.2 判断手机号和验证码是否为空
        String phone = dto.getPhone();
        String password = dto.getPassword();

        // 2. 为空（游客）
        if (StringUtils.isEmpty(phone) && StringUtils.isEmpty(password)) {
            User youke = new User();
            youke.setId(0L);

            return getLoginAuthVo(youke);
        }

        // 3. 不为空（正常登录）
        // 3.1 手机号格式校验
        boolean mobile = Validator.isMobile(phone);
        if (!mobile) {
            throw new RuntimeException("手机号格式错误");
        }
        // 3.2 到数据库查询手机号是否存在
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getPhone, phone);
        User user = userMapper.selectOne(wrapper);

        // 3.4 手机号不存在
        if (user == null) {
            // 3.4.1 创建手机号
            User newUser = new User();
            newUser.setId(IdUtil.getSnowflakeNextId());
            newUser.setFlag(0);
            newUser.setImage("");
            newUser.setIsIdentityAuthentication(false);
            newUser.setSex(false);
            newUser.setStatus(true);
            newUser.setCreatedTime(new Date());

            int insertResult = userMapper.insert(newUser);
            if (insertResult != 1) {
                throw new RuntimeException("创建用户异常");
            }

            // 3.4.1 组装用户信息 -> 生成token
            // 3.4.2 返回组装后的信息
            return getLoginAuthVo(newUser);
        }

        // 3.3 手机号存在
        // 3.3.1 组装用户信息 -> 生成token
        // 3.3.2 返回组装后的信息
        return getLoginAuthVo(user);
    }

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Override
    public Boolean userFollow(FollowDto dto) {

        // 1. 入参判断
        if (dto == null) {
            throw new RuntimeException("入参不能为空");
        }

        Integer operation = dto.getOperation();
        Long authorId = dto.getAuthorId();
        Long userId = 4L;

        // 2. 判断当前操作是关注还是取消关注 operation
        if (operation == 0) {
            // 3. 关注
            // 3.1 当前用户是否已关注过目标用户
            Object o = redisTemplate.opsForHash().get("USER_FOLLOW_" + authorId, Long.toString(userId));
            // 3.1.2 否：调用Redis方法，将当前用户和目标用户的id写入到Redis中
            if (o == null) {
                redisTemplate.opsForHash().put("USER_FOLLOW_" + authorId,  Long.toString(userId), Long.toString(System.currentTimeMillis()));
            }
            // 3.1.1 是：返回成功
        } else {
            // 4. 取消关注
            // 4.1 当前用户是否已关注过目标用户
            Object o = redisTemplate.opsForHash().get("USER_FOLLOW_" + authorId,  Long.toString(userId));
            // 4.1.1 是：移除redis的绑定关系
            if (o != null) {
                redisTemplate.opsForHash().delete("USER_FOLLOW_" + authorId,  Long.toString(userId));
            }
            // 4.1.2 否：返回成功
        }

        return true;
    }


    public LoginAuthVo getLoginAuthVo(User user) {
        // 2.1 生成token
        Map<String, Object> payload = new HashMap<>();
        payload.put("id", user.getId());
        String token = JWTUtil.createToken(null, payload, "heimaleadnews".getBytes());

        // 2.2 组装用户信息（用户id：0）
        LoginAuthVo vo = new LoginAuthVo();
        vo.setUser(user);
        vo.setToken(token);

        // 2.3 返回组装后的信息
        return vo;
    }
}
